#!/bin/bash

set -e
set -o pipefail

unset dts
unset rtl
unset SED

while [ "$1" != "" ]
do
    case "$1"
    in
    --dts)      dts="$2";       shift 2;;
    --rtl)      rtl=1;          shift 1;;
    *) echo "$0: Unknown argument $1"; exit 1;;
    esac
done

if [ "${dts}" == "" ]
then
    echo "$0: please provide '--dts' option" >&2
    exit 1
fi

# When installed on MacOS with Homebrew, GNU sed is named gsed.
# If gsed exists, use it.
if [ "`which gsed`" == "" ]; then
    SED=sed
else
    SED=gsed
fi

# Add numintbits for the clic node if it doesn't exist

if [ `grep -c 'sifive,clic0' ${dts}` -ne 0 ]; then
    if [ `grep -c 'sifive,numintbits' ${dts}` -eq 0 ]; then
        echo "$0: Clic missing numintbits in  ${dts}."

        ${SED} -i 's/interrupt-controller@2000000 {/interrupt-controller@2000000 {\n\t\t\tsifive,numintbits = <2>;/g' ${dts}

        echo -e "$0: \tAdded numintbits to clic."
    fi
fi

# Add compat string for the global-interrupt node if it doesn't exist

if [ `grep -c 'global-external-interrupts {' ${dts}` -ne 0 ]; then
    if [ `grep -c 'sifive,global-external-interrupts0' ${dts}` -eq 0 ]; then
        echo "$0: Global external interrupts missing compat string in ${dts}."

        ${SED} -i 's/global-external-interrupts {/global-external-interrupts {\n\t\t\tcompatible = "sifive,global-external-interrupts0";/g' ${dts}

        echo -e "$0: \tAdded compat string to global-external-interrupts."
    fi
fi

# Add compat string for the local-interrupt node if it doesn't exist

if [ `grep -c 'local-external-interrupts-0 {' ${dts}` -ne 0 ]; then
    if [ `grep -c 'sifive,local-external-interrupts0' ${dts}` -eq 0 ]; then
        echo "$0: Local external interrupts missing compat string in ${dts}."

        ${SED} -i 's/local-external-interrupts-0 {/local-external-interrupts {\n\t\t\tcompatible = "sifive,local-external-interrupts0";/g' ${dts}

        echo -e "$0: \tAdded compat string to local-external-interrupts-0."
    fi
fi

# Add a chosen node if it does not exist

if [ `grep -c 'chosen' ${dts}` -eq 0 ]; then
    ${SED} -i "/cpus/i chosen {\n};" ${dts}

    echo -e "$0: \tAdded chosen node"
fi

# Add a stdout-path to the chosen node if one doesn't exist and a serial port does

if [ `grep -c 'stdout-path' ${dts}` -eq 0 ]; then
    if [ `grep -c 'sifive,uart0' ${dts}` -ne 0 ]; then
        echo "$0: stdout-path property not given, but a UART device exists."

        serial_node=`grep -oP "serial@[[:xdigit:]]+" ${dts} | sort | uniq | head -n 1`
        if [ "${rtl}" ] ; then
            serial_path="/soc/${serial_node}:100000000"
        else
            serial_path="/soc/${serial_node}:115200"
        fi

        ${SED} -i "/chosen/a stdout-path=\"${serial_path}\";" ${dts}

        echo -e "$0: \tAdded stdout-path ${serial_path}"

    # If no UART exists, use the trace encoder
    elif [ `grep -c 'sifive,trace' ${dts}` -ne 0 ]; then
        echo "$0: stdout-path property not given, but a trace encoder exists."

        trace_node=`grep -oP "trace@[[:xdigit:]]+" ${dts} | sort | uniq | head -n 1`
        trace_path="/soc/${trace_node}:115200"

        ${SED} -i "/chosen/a stdout-path=\"${trace_path}\";" ${dts}

        echo -e "$0: \tAdded stdout-path ${trace_path}"

    # If an HTIF exists, use it
    elif [ `grep -c 'ucb,htif0' ${dts}` -ne 0 ]; then
        echo "$0: stdout-path property not given, but an htif exists."

        ${SED} -i "/chosen/a stdout-path=\"/htif\";" ${dts}

        echo -e "$0: \tAdded stdout-path /htif"
    fi

fi

# Multicore configs have a monitor core for hart 0, so to get the right benchmark
# scores we should request boot from hart 1

if [ `grep -c 'cpu@1' ${dts}` -ne 0 ]; then
    if [ `grep -c 'metal,boothart' ${dts}` -eq 0 ]; then

        label=`grep "cpu@1" ${dts} | ${SED} -E "s/^\s+(\S+):.*$/\1/g"`

        ${SED} -i "/chosen/a metal,boothart = <&${label}>;" ${dts}
    fi
fi

# FPGA targets need a 0x400000 byte offset into their SPI flash

# Is the target an FPGA?
if [ `echo ${dts} | grep -c 'arty'` -ne 0 -o `echo ${dts} | grep -c 'fpga'` -ne 0 ] ; then
    # Is there a metal,entry property in the chosen node?
    if [ `grep -c 'metal,entry' ${dts}` -eq 0 ] ; then
        echo "$0: FPGA target needs metal,entry property to set boot offset."

        # Find the SPI device with the lowest base address
        first_spi_node=`grep -oE "spi@[[:xdigit:]]+?" ${dts} | sort | head -n 1`

        # Get the DTS node label of that SPI device
        spi_entry_label=`grep -oE "[^[:space:]]+?:\s+?${first_spi_node}" ${dts} | cut -d ':' -f 1`

        ${SED} -i "/chosen/a metal,entry = <&${spi_entry_label} 0x400000>;" ${dts}

        echo -e "$0: \tAdded metal,entry for SPI node ${first_spi_node} with label ${spi_entry_label}"
    fi
fi

